﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;

namespace PP.PaintLib
{
    public class PPICON
    {
		/// <summary>
		/// 保存为ICO文件
		/// </summary>
		/// <param name="filePath">文件路径</param>
		/// <param name="width">宽度</param>
		/// <param name="height">高度</param>
		/// <returns>true:成功 false:失败</returns>
		public static bool SaveAsICON(string filePath, int width = 0, int height = 0)
		{
			try
			{
                //基于源文件路径，仅修改后缀名为ico
                string fileDirectory = Path.GetDirectoryName(filePath);
				string fileSavePath = Path.Combine(fileDirectory, Path.GetFileNameWithoutExtension(filePath)) + ".ico";

				using (Bitmap bm = new Bitmap(filePath))
				{
                    //尺寸范围：【1-255，1-255】
                    width = width == 0 ? bm.Width : width;
					width = width > 255 ? 255 : width;

					height = height == 0 ? bm.Height : height;
					height = height > 255 ? 255 : height;

					//转换结果
					bool isSuccess = ConvertImageToIcon(filePath, fileSavePath, new Size(width, height));
					if (!isSuccess)
					{
						return isSuccess;
					}
					//转换成功，打开文本保存所在目录
					Process.Start("explorer.exe", fileDirectory);
					return isSuccess;
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("转化失败。错误信息：" + ex.Message);
				return false;
			}
		}

		/// <summary>
		/// 图片转换为ico文件
		/// </summary>
		/// <param name="origin">原图片路径</param>
		/// <param name="destination">输出ico文件路径</param>
		/// <param name="iconSize">输出ico图标尺寸，不可大于255x255</param>
		/// <returns>是否转换成功</returns>
		private static bool ConvertImageToIcon(string origin, string destination, Size iconSize)
		{
            if (iconSize.Width > 255 || iconSize.Height > 255)
            {
                return false;
            }

			Bitmap originBMP = new Bitmap(origin);
            Image image = new Bitmap(originBMP, iconSize); //先读取已有的图片为bitmap，并缩放至设定大小
			MemoryStream bitMapStream = new MemoryStream(); //存原图的内存流
			MemoryStream iconStream = new MemoryStream(); //存图标的内存流
			image.Save(bitMapStream, ImageFormat.Png); //将原图读取为png格式并存入原图内存流，保证原图透明度、清晰度
			BinaryWriter iconWriter = new BinaryWriter(iconStream); 

			//下面是根据原图信息，进行文件头写入
			iconWriter.Write((short)0);//0-1保留
            iconWriter.Write((short)1);//2-3文件类型。1=图标, 2=光标
            iconWriter.Write((short)1);//4-5图像数量（图标可以包含多个图像）
            iconWriter.Write((byte)image.Width);//6图标宽度
            iconWriter.Write((byte)image.Height);//7图标高度
            iconWriter.Write((short)0);//8颜色数（若像素位深>=8，填0。这是显然的，达到8bpp的颜色数最少是256，byte不够表示） ；9保留。必须为0
            iconWriter.Write((short)0);//10-11调色板
            iconWriter.Write((short)32);//12-13位深
            iconWriter.Write((int)bitMapStream.Length);//14-17位图数据大小
            iconWriter.Write(22); //18 - 21位图数据起始字节

            //写入图像体至目标图标内存流
            iconWriter.Write(bitMapStream.ToArray());
			//保存流，并将流指针定位至头部以Icon对象进行读取输出为文件
			iconWriter.Flush();
			iconWriter.Seek(0, SeekOrigin.Begin);
			Stream iconFileStream = new FileStream(destination, FileMode.Create);
			Icon icon = new Icon(iconStream);
			icon.Save(iconFileStream); //储存图像

			 //下面开始释放资源
            iconFileStream.Close();
			iconWriter.Close();
			iconStream.Close();
			bitMapStream.Close();
            originBMP.Dispose();
            icon.Dispose();
			image.Dispose();
			iconFileStream.Dispose();

            return File.Exists(destination);
		}

    }
}
